# coding: utf-8

# -------------------------------------------------------------------------------
# Name:         import_api_task.py
# Description:  导入接口数据
# Author:       XiangjunZhao
# EMAIL:        2419352654@qq.com
# Date:         2019/12/12 11:44
# -------------------------------------------------------------------------------
import json
import logging
from json import JSONDecodeError

from apps.HttpAutoTestService.core.builtin.functions import get_timestamp
from apps.HttpAutoTestService.models import Api, Module, Testcase

__all__ = ['import_api_from_postman']

logger = logging.getLogger(__name__)


def import_api_from_postman(user=None, project=None, contents=None, create_testcase=False):
    """
    通过postman导入接口数据
    Args:
        user: 操作用户
        project: 所属项目
        contents: 文件内容
        create_testcase: 创建测试用例

    Returns:

    """

    # 定义解析接口数据的方法
    def _parse_api(content, module, create_testcase):
        if isinstance(content, list):
            for item in content:
                _parse_api(content=item, module=module, create_testcase=create_testcase)
        elif isinstance(content, dict):
            if 'item' in content.keys():
                module_name = content.get('name')
                module = None
                if module_name:
                    module = Module.objects.filter(name=module_name, project_id=project.id, is_deleted=False).first()
                    if not module:
                        # module在系统中不存在
                        if module_name in module_name_list:
                            # Module已经存在于module_list列表中
                            for module_temp in module_list:
                                if module_name == module_temp.name:
                                    module = module_temp
                                    break
                        else:
                            # Module不存在于module_list列表中，新建Module，并将其存放到module_list列表中
                            module = Module(**{
                                'name': module_name,
                                'project': project,
                                'creator': user,
                                'modifier': user
                            })
                            module_name_list.append(module_name)
                            module_list.append(module)
                _parse_api(content=content.get('item'), module=module, create_testcase=create_testcase)
            elif 'request' in content.keys():
                # api名称
                name = content.get('name')
                # api请求参数类型
                request_data_type = 'Json'
                # api请求参数
                request_data = {}
                request = content.get('request')
                if request:
                    # api请求方法
                    method = request.get('method', 'GET').upper()
                    # api请求头
                    headers = request.get('header')
                    headers = {item.get('key'): item.get('value') for item in headers} if headers else {}
                    # 请求认证
                    auth = request.get('auth')
                    if auth:
                        auth_type = auth.get('type')
                        if auth.get(auth_type):
                            auth_value = {item.get('key'): item.get('value') for item in auth.get(auth_type) if
                                          (item and item.get('key'))}
                            headers.update(auth_value)

                    # api请求URL
                    url = ''
                    # api查询参数
                    request_params = ''
                    # postman请求url（包含请求路径和查询参数）
                    request_url = request.get('url')
                    if request_url:
                        path = request_url.get('path')
                        query = request_url.get('query')
                        if path:
                            url = r'/'.join(path)
                        if query:
                            request_params = '&'.join(
                                [f"{item.get('key')}={item.get('value', '')}" for item in query if item])
                    # postman请求消息体
                    request_body = request.get('body')
                    if request_body:
                        # api接口请求参数类型
                        request_mode = request_body.get('mode')
                        # api接口请求参数
                        request_data = request_body.get(request_mode)
                        if request_data and 'raw' == request_mode:
                            request_data_type = 'Json'
                            try:
                                request_data = json.loads(request_data)
                            except JSONDecodeError:
                                request_data = {}
                        elif request_data and request_mode in ('formdata', "urlencoded"):
                            request_data_type = 'Form Data'
                            if isinstance(request_data, list):
                                request_data = {item.get('key'): '' for item in request_data}

                    # 已存在的api
                    api = Api.objects.filter(project_id=project.id, url=url, method=method, is_deleted=False).first()
                    if not api:
                        # 接口未存在于系统中，需要新增
                        api = Api(name=name, url=url, request_params=request_params,
                                  method=method, headers=headers, request_data_type=request_data_type,
                                  request_data=request_data, project=project, module=module, creator=user,
                                  modifier=user)
                        api_list.append(api)
                    else:
                        logger.info('通过postman文件导入的接口已存在，接口：{}'.format(url + '\t' + method))
                    if create_testcase:
                        testcase_name = name
                        if Testcase.objects.filter(name=testcase_name):
                            testcase_name = f'{testcase_name}-{str(get_timestamp(16))[10:]}'
                        testcase = Testcase(name=testcase_name, url=url, request_params=request_params, headers=headers,
                                            request_data_type=request_data_type, request_data=request_data,
                                            expect_result=expect_result, api=api, creator=user, modifier=user)
                        testcase_list.append(testcase)

    # 将要新增的模块列表
    module_list = []
    # 存放创建了Module的名称
    module_name_list = []
    # 将要新增的接口
    api_list = []
    # 将要新增的用例
    testcase_list = []
    # 测试用例默认期望结果
    expect_result = [{
        'output': [],
        'validate': [{'check': 'status_code', 'expect': 200, 'comparator': 'eq'}],
    }]
    for content in contents:
        content = json.loads(content)
        _parse_api(content=content, module=None, create_testcase=create_testcase)
    Module.objects.bulk_create(module_list)
    Api.objects.bulk_create(api_list)
    msg = f'通过postman文件成功导入{len(module_list)}个模块，{len(api_list)}个接口'
    if create_testcase:
        Testcase.objects.bulk_create(testcase_list)
        msg = f'通过postman文件成功导入{len(module_list)}个模块，{len(api_list)}个接口，{len(testcase_list)}个用例'
    logger.info(msg)
    return msg
